package com.conversationboard.model;

import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPathExpressionException;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.filefilter.FileFilterUtils;
import org.xml.sax.SAXException;

import com.conversationboard.config.Configuration;
import com.conversationboard.database.Database;
import com.conversationboard.database.Queries;

/**
 * Collection of stylesheets. Responsible for loading them from the XML file and
 * also for getting the user's current stylesheet and setting the users current
 * stylesheet.
 * 
 * @author Keith Watson
 * 
 */

public class StyleSheets {

	private static String stylesheetsPath;
	private static Pattern commentPattern = Pattern.compile("/\\*(.*)\\*/", (Pattern.CASE_INSENSITIVE | Pattern.DOTALL));


	public static void setStylesheetsPath(String path) {
		stylesheetsPath = path;
	}


	public static String getStylesheetsPath() {
		return stylesheetsPath;
	}


	public synchronized static List<StyleSheet> getStyleSheetFileNames() throws ParserConfigurationException, SAXException, XPathExpressionException, IOException {

		return load();
	}


	public static String getStyleSheetFileName(Cookie[] cookies) {

		String styleSheetFileName = Configuration.getInstance().getDefaultStyleSheet();

		if (cookies != null) {
			for (Cookie cookie : cookies) {
				if (cookie.getName().equals("StyleSheet")) {

					String fileName = cookie.getValue();

					if (!fileName.contains("/")) {
						styleSheetFileName = cookie.getValue();
					}

				}
			}
		}

		return styleSheetFileName;
	}


	public static void setStyleSheetFileName(User user, String fileName, HttpServletResponse response) throws SQLException {

		Cookie cookie = new Cookie("StyleSheet", fileName);
		cookie.setMaxAge(999999999);
		response.addCookie(cookie);

		/* Record the fact on the database, just for interest */

		Connection connection = null;

		try {
			connection = Database.getConnection();

			PreparedStatement statement = connection.prepareStatement(Queries.UPDATE_STYLESHEET);
			statement.setString(1, fileName);
			statement.setString(2, user.getLoginId());

			statement.executeUpdate();

		} finally {
			Database.close(connection);
		}

	}


	/**
	 * Load the stylesheets from disk. Used to require an XML configuration file, but refactor to just read the files from disk. The
	 * comment at the start of the stylesheet is used for the stylesheet's description.
	 * 
	 * @return
	 * @throws IOException
	 * @throws ParserConfigurationException
	 * @throws SAXException
	 * @throws XPathExpressionException
	 */

	private synchronized static List<StyleSheet> load() throws IOException, ParserConfigurationException, SAXException, XPathExpressionException {

		List<StyleSheet> styleSheets = new ArrayList<StyleSheet>();

		FileFilter filter = FileFilterUtils.suffixFileFilter("css");
		File directory = new File(stylesheetsPath);
		File[] files = directory.listFiles(filter);

		for (File file : files) {

			/* Open each file, extract the comment at the top (if it exists) and close it */

			List<String> lines = FileUtils.readLines(file, "UTF-8");
			String description = "";

			if (lines.size() > 0) {
				Matcher matcher = commentPattern.matcher(lines.get(0));

				if (matcher.find()) {
					description = matcher.group(1);
				}
			}

			StyleSheet styleSheet = new StyleSheet(file.getName(), description);
			styleSheets.add(styleSheet);
		}

		Collections.sort(styleSheets);
		
		return styleSheets;

	}

}
